home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
101_01
/
yahtzee.c
< prev
next >
Wrap
Text File
|
1985-11-13
|
12KB
|
385 lines
/* YAHTZEE Dice game Steve Ward
* USAGE:
*
* yahtzee [-dn] name1 name2 name3 ...
* where the namei are player's names, prefixed by = for automated
* (computer) players.
*
* yahtzee
* for solitaire.
*
* USE special function keys to select dice, roll selected dice, and end
* an inning; keypad up/down arrows select where to enter your score.
*
* See YAHTZEE.HLP for full instructions.
*
* COMPILE and CLINK with CIO.CRL!
*/
#define ROLLX 39 /* Coordinates for light buttons. */
#define DONEX 46
#define PASSX 53
#define OOPSX 60
#define OOPSC 'R'
#define PASSC 'Q'
#define DONEC 'P'
#define ROLLC 'J'
#define GOX 45 /* Coordinates for prompt. */
#define GOY 22
#define GAMEY 20
#define SCOREX 30 /* leftmost column for scores */
#define DIEY 22
#define LABLIN 24 /* Line for labels */
#define PLAYERS 10 /* Max number of players */
#define NONE 127 /* char-size illegal value. */
char Dice[5];
char nplayers; /* actual number of players. */
char Potent[13]; /* Potential score... */
char PotKind, PotSum, PotStr; /* Filled by Pot */
char PotMax, PotCnt;
struct Player
{ char Scores[13]; /* Scores, or 127 iff none yet. */
char Select; /* Currently selected category. */
char Col; /* Column number, for scores. */
char Name[40]; /* Name of player. */
int Total; /* total score. */
int Games;
} Who[PLAYERS];
/* Initialize a player: */
iplayer(name, pl)
char *name; struct Player *pl;
{ char i, *fake; fake = "==0==";
if ((!name[1]) && (*name == '=')) { name = fake; name[3]++; }
for (i=0; i<13; i++) pl->Scores[i] = NONE;
pl->Select = NONE;
for (i=0; pl->Name[i] = name[i]; i++); }
Buzz() { putchar(7); }
MoveTo(x, y) { puts("\033Y"); putchar(y+32); putchar(x+32); }
char ShowX, ShowY, *ShowSc; int ShowTot;
Show1(n, flag)
char n, flag;
{ int val;
MoveTo(ShowX, ShowY++);
if (n == 255) val = ShowTot; else val = ShowSc[n];
if (!flag) { puts("\033p"); val = Potent[n]; }
else if (flag == 44) puts("\033p");
if (val == NONE) puts(" ? ");
else { printf(" %2d", val); ShowTot += val; }
if (!flag || (flag == 44)) puts("\033q"); }
Show(pl) /* Show the scores of a player. */
char pl;
{ struct Player *p; char cc, tot, f, j;
Pot(pl);
ShowX = (p = &Who[pl])->Col-1; ShowY = 1; ShowTot = 0;
ShowSc = p->Scores; cc = 0; f = p->Select;
Show1(cc++,f--); Show1(cc++,f--); Show1(cc++,f--);
Show1(cc++,f--); Show1(cc++,f--); Show1(cc++,f--);
tot = ShowTot; Show1(255,44); ShowTot = j = tot>=63? 35:0;
Show1(255,44);
tot = ShowTot = tot+j; Show1(255,44); ShowTot = tot;
ShowY++;
Show1(cc++,f--); Show1(cc++,f--); Show1(cc++,f--);
Show1(cc++,f--); Show1(cc++,f--); Show1(cc++,f--);
Show1(cc++,f--);
p->Total = ShowTot;
Show1(255,44); }
char Straight(die) /* Gives longest straight starting at die */
{ char i, j;
for (i=1; i<6; i++)
{ die++;
for (j=0; j<5; j++) if (Dice[j] == die) goto hit;
break;
hit: continue; }
return i; }
char Kind(die) /* Gives number of dice of count die */
{ char count, i;
for (i=count=0; i<5; i++) if (die == Dice[i]) count++;
return count; }
Pot(pl) /* Compute potential scores for player. */
char pl;
{ char i,j,k;
for (i=0; i<13; i++) Potent[i] = 0;
for (i=0; i<5; i++) if (((j = Dice[i])>0) && (j<7)) Potent[j-1] += j;
for (PotMax=PotSum=i=PotKind=0; i<5; i++)
{ PotKind |= (1<<(j=Kind(k=Dice[i]))); PotSum += Dice[i];
if (j>PotMax) { PotMax=j; PotCnt=k; }}
Potent[12] = PotSum;
if ((PotKind & 0xC) == 0xC) Potent[8] = 25;
if (PotKind & 0x38) Potent[6] = PotSum;
if (PotKind & 0x30) Potent[7] = PotSum;
if (PotKind & 0x20) Potent[11] = 50;
for (i=PotStr=0; i<5; i++) if ((j = Straight(Dice[i])) > PotStr)
PotStr=j;
if (PotStr >= 4) Potent[9] = 30;
if (PotStr == 5) Potent[10] = 40; }
Play(pl) /* Make a player's move; returns 0 iff OK. */
char pl;
{ Pot(pl);
Who[pl].Scores[Who[pl].Select] = Potent[Who[pl].Select]; }
Bd(f)
char f;
{ char i, *cc;
cc = " . ";
if (f == 1) { puts("\033F"); cc = "iii"; }
else if (!f) puts("\033q");
for (i=((80-SCOREX)/3); i--;) puts(cc);
puts("\033p\033G\n"); }
Board()
{ char i;
printf("\033H\033J\033p\033G");
printf(" H89 YAHTZEE 1.1 \033F");
for (i=48; i--;) putchar('i'); puts("\033G\n");
printf(" ACES ADD 1's "); Bd(0); /* Y = 1 */
printf(" TWOS ADD 2's "); Bd(0);
printf(" THREES ADD 3's "); Bd(0);
printf(" FOURS ADD 4's "); Bd(0);
printf(" FIVES ADD 5's "); Bd(0);
printf(" SIXES ADD 6's "); Bd(0);
printf(" Subtotal . . . . . "); Bd(2); /* Y = 7 */
printf(" Bonus iff >= 63 35 "); Bd(2); /* Y = 8 */
printf("TOTAL ABOVE . . . . . "); Bd(2); /* Y = 9 */
printf(" \n");
printf(" 3 of a kind SUM "); Bd(0); /* Y = 11 */
printf(" 4 of a kind SUM "); Bd(0);
printf(" Full House 25 "); Bd(0);
printf(" 4 Straight 30 "); Bd(0);
printf(" 5 Straight 40 "); Bd(0);
printf(" YAHTZEE 50 "); Bd(0);
printf(" Chance SUM "); Bd(0);
printf("TOTAL SCORE . . . . . "); Bd(2);
MoveTo(0, GAMEY);
printf("GAMES . . . . . . . "); Bd(1);
puts("\033p\033F");
MoveTo(ROLLX, LABLIN); puts("i ROLL i");
MoveTo(DONEX, LABLIN); puts("i DONE i");
MoveTo(PASSX, LABLIN); puts("i i");
MoveTo(OOPSX, LABLIN); puts("i OOPS i");
puts("\033q\033G");
}
#define TOP 0
#define MID 8
#define BOT 16
Die(number, count)
{ char i, j;
if (count) puts("\033p\033F");
for (i=0; i<3; i++)
{ MoveTo(4+(7*number), DIEY+i);
switch (count+(i<<3))
{ case TOP: case MID: case BOT:
case TOP+1: case BOT+1:
case MID+2:
case MID+4: puts(" "); break;
case TOP+2:
case TOP+3: puts("^ "); break;
case MID+1:
case MID+3:
case MID+5: puts(" ^ "); break;
case BOT+2:
case BOT+3: puts(" ^"); break;
case TOP+4: case BOT+4:
case TOP+5: case BOT+5:
case TOP+6: case MID+6: case BOT+6:
puts("^ ^"); break; }}
Dice[number] = count;
puts("\033G\033q"); }
Roll()
{ char i;
for (i=0; i<5; i++) if (!Dice[i]) Die(i, 1+rand()%6); }int DTime;
Go(rolls, player)
char rolls, player;
{ char ch, i, save[5];
Pot(player);
for (i=0; i<5; i++) Dice[i] = 0; Roll();
Who[player].Select = 12;
if (!Cycle(player, 1)) return 0;
Top: for (i=0; i<5; i++) save[i] = Dice[i];
nsc: Show(player);
for (;;)
{ MoveTo(GOX, GOY);
printf("\033q\033G%s's move: %d rolls left. \033K",
Who[player].Name, rolls);
esc: if (Who[player].Name[0] == '=') ch = Auto(player, rolls);
else ch = getchar();
switch (ch)
{ case 033: goto esc;
case '8': Cycle(player, -1); Show(player); continue;
case ' ':
case '2': Cycle(player, 1); Show(player); continue;
case 'S': case 'T': case 'U': case 'V': case 'W':
if (!rolls) Buzz();
else Die(ch - 'S', 0); continue;
case 0177:
case OOPSC: for (i=0; i<5; i++) Die(i, save[i]); continue;
case ROLLC: if (rolls>0) { Roll(); rolls--; }
else Buzz(); goto Top;
case DONEC:
case '\r':
case PASSC: Play(player);
Who[player].Select = NONE; Show(player);
return ch;
default: putchar(7); continue; }}}
/* Make move for a computer player: */
int AutoPar[10]; /* Heuristic parameters -HA#, -HB#, etc. */
char Auto(pl, rolls)
char pl, rolls;
{ char gofor, choice, i, j, *sc;
int value[13], target[6], best, n;
sc = Who[pl].Scores;
Pot(pl);
MoveTo(GOX, GOY+1); printf("Hmmm ... lemme think.\033K",
value[choice]);
Delay(DTime);
for (i=0; i<13; i++)
{ if (sc[i] != NONE) value[i] = i-99;
else if (i<6) value[i] = 2*(Potent[i]-3*(i+1));/* face counts */
else if (i==6) value[i] = Potent[i]-20; /* 3 of a kind */
else if (i==7) value[i] = Potent[i]-15; /* 4 of a kind */
else if (i==9) value[i] = Potent[i]-12; /* 4 straight */
else if (i==10) value[i] = P